package com.example.sunsg.okhttptest.customview;

import android.content.Context;
import android.support.v4.view.GestureDetectorCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.widget.FrameLayout;
import android.widget.Scroller;


import java.util.concurrent.atomic.AtomicBoolean;

public class HeadsUpSlideContainer extends FrameLayout {

    private enum Orientation{
        NONE,

        HORIZONTAL,//水平

        VERTICAL,//竖直

    }


    public HeadsUpSlideContainer(Context context) {
        super(context);
        initViews();
    }

    public HeadsUpSlideContainer(Context context, AttributeSet attrs) {
        super(context, attrs);
        initViews();
    }

    public HeadsUpSlideContainer(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initViews();
    }

    private GestureDetectorCompat detectorCompat;
    private Scroller mScroller;
    private AtomicBoolean mbFling = new AtomicBoolean(false);
    private static final String TAG = "HeadsUpContainer";
    private static final boolean DEBUG = true;
    private static int SWIPE_SPEED = 0;
    private SwipeLayout.SwipeListener mSwipeListener;
    private Orientation mOrientation;
    private boolean mCanSlideDown = false;//是否可以向下滑动

    public void setOnSwipeListener(SwipeLayout.SwipeListener swipeListener) {
        mSwipeListener = swipeListener;
    }

    private void initViews() {
        SWIPE_SPEED = ViewConfiguration.get(getContext()).getScaledMaximumFlingVelocity()/5;
        mScroller = new Scroller(getContext());
        mOrientation = Orientation.NONE;
        detectorCompat = new GestureDetectorCompat(getContext(), new GestureDetector.SimpleOnGestureListener(){
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                if (DEBUG) {
                    Log.d(TAG, "onSingleTapUp ");
                }
                performClick();
                return super.onSingleTapUp(e);
            }

            @Override
            public void onLongPress(MotionEvent e) {
                if (DEBUG) {
                    Log.d(TAG, "onLongPress ");
                }
                super.onLongPress(e);
            }

            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
                if (DEBUG) {
                    Log.d(TAG, "onScroll : distanceX = " + distanceX +" distanceY = " + distanceY);
                }
                setScrollOrientation(distanceX,distanceY);
                if(isHorizontal()){
                    scrollBy((int)(distanceX), 0);
                }else if(isVertical()){
                    if(distanceY < 0){
                        //向下滑动
                        if(mCanSlideDown){
                            //是否可以向下滑动
                            scrollBy(0,(int)(distanceY));
                        }
                    }else{
                        scrollBy(0,(int)(distanceY));
                    }
                }
                return true;
            }

            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                if (DEBUG) {
                    Log.d(TAG, "onFling velocityX = " + velocityX + " & swipe_speed = " + SWIPE_SPEED);
                }
                if(isHorizontal()){
                    onFlingX(velocityX);
                }else if(isVertical()){
                    onFlingY(velocityY);
                }
                return super.onFling(e1, e2, velocityX, velocityY);
            }

            @Override
            public void onShowPress(MotionEvent e) {
                super.onShowPress(e);
                if (DEBUG) {
                    Log.d(TAG, "onShowPress");
                }
            }

            @Override
            public boolean onDown(MotionEvent e) {
                if (DEBUG) {
                    Log.d(TAG, "onDown");
                }
                if (!mScroller.isFinished()) {
                    mScroller.abortAnimation();
                    mScroller.forceFinished(true);
                }
                mbFling.set(false);
                return true;
            }

            @Override
            public boolean onDoubleTap(MotionEvent e) {
                return super.onDoubleTap(e);
            }

            @Override
            public boolean onDoubleTapEvent(MotionEvent e) {
                return super.onDoubleTapEvent(e);
            }

            @Override
            public boolean onSingleTapConfirmed(MotionEvent e) {
                return super.onSingleTapConfirmed(e);
            }

            @Override
            public boolean onContextClick(MotionEvent e) {
                return super.onContextClick(e);
            }
        });
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        detectorCompat.onTouchEvent(event);
        if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP) {
            if (DEBUG) {
                Log.d(TAG, "onTouchEvent : scrollX = " + getScrollX() + " & mMaxDistance = " + getWidth());
            }
            if (!mbFling.get()) {
                if(isHorizontal()){
                    swipeGestureX();
                }else if(isVertical()){
                    swipeGestureY();
                }
            }
        }
        return true;
    }

    /**
     * 水平方向up之后滑动
     */
    private void swipeGestureX() {
        int scrollX = getScrollX();

        if (DEBUG) {
            Log.d(TAG, "swipeGesture : scrollX = " + scrollX + " & mMaxDistance = " + getWidth());
        }

        if (scrollX > 0) {
            if (scrollX >= getWidth() / 2f) {
                mScroller.startScroll(scrollX, 0, getWidth()-scrollX, 0);
            } else {
                mScroller.startScroll(scrollX, 0, -scrollX, 0);
            }
            invalidate();
        } else if (scrollX < 0){
            if (scrollX <= -getWidth() / 2f) {
                mScroller.startScroll(scrollX, 0, -getWidth() + scrollX, 0);
            } else {
                mScroller.startScroll(scrollX, 0, -scrollX, 0);
            }
            invalidate();
        }
    }

    /**
     * 竖直方向up之后滑动
     */
    private void swipeGestureY() {
        int scrollY = getScrollY();

        if (DEBUG) {
            Log.d(TAG, "swipeGesture : scrollY = " + scrollY + " & mMaxDistance = " + getHeight());
        }

        if (scrollY > 0) {
            mScroller.startScroll(0, scrollY, 0, getHeight() - scrollY);
            invalidate();
        } else if (scrollY < 0) {
            if (mCanSlideDown) {
                mScroller.startScroll(0, scrollY, 0, -getHeight() + scrollY);
                invalidate();
            }
        }
    }

    /**
     * 水平方向滑动
     * @param velocityX 速度
     */
    private void onFlingX(float velocityX){
        if(isVertical()) return;
        if (Math.abs(velocityX) > SWIPE_SPEED) {
            mbFling.set(true);
            if (DEBUG) {
                Log.d(TAG, "onFling velocityX = " + velocityX);
            }

            int scrollX = getScrollX();
            if (scrollX > 0) {
                mScroller.startScroll(scrollX, 0, getWidth()-scrollX, 0);
            } if (scrollX < 0) {
                mScroller.startScroll(scrollX, 0, -getWidth()+scrollX, 0);
            }
            invalidate();
        }
    }

    /**
     * 竖直方向滑动
     * @param velocityY 速度
     */
    private void onFlingY(float velocityY){
        if(isHorizontal()) return;
        if (Math.abs(velocityY) > SWIPE_SPEED) {
            mbFling.set(true);
            if (DEBUG) {
                Log.d(TAG, "onFling velocityY = " + velocityY);
            }

            int scrollY = getScrollY();
            if (scrollY > 0) {
                mScroller.startScroll(0, scrollY, 0, getHeight() - scrollY);
            }
            if (scrollY < 0) {
                if (mCanSlideDown) {
                    mScroller.startScroll(0, scrollY, 0, -getHeight() + scrollY);
                }
            }
            invalidate();
        }
    }

    /**
     * 设置滑动方向
     * @param distanceX
     * @param distanceY
     */
    private void setScrollOrientation(float distanceX, float distanceY){
        if(Math.abs(distanceX) > Math.abs(distanceY)){
            setOrientation(Orientation.HORIZONTAL);
        }else{
            setOrientation(Orientation.VERTICAL);
        }
    }

    public void setOrientation(Orientation orientation){
        if(mOrientation == Orientation.NONE){
            mOrientation = orientation;
        }
    }

    public void setOrintationNONE(){
        mOrientation = Orientation.NONE;
    }

    private boolean isHorizontal(){
        return mOrientation == Orientation.HORIZONTAL;
    }

    private boolean isVertical(){
        return mOrientation == Orientation.VERTICAL;
    }

    public void canSlideDown(boolean can){
        mCanSlideDown = can;
    }


    @Override
    public void computeScroll() {
        super.computeScroll();
        if (mScroller.computeScrollOffset()) {
            if(isHorizontal()){
                scrollTo(mScroller.getCurrX(), 0);
            }else if(isVertical()){
                scrollTo(0,mScroller.getCurrY());
            }
            postInvalidate();
        }

        if (mScroller.isFinished()) {

            if(isHorizontal()){
                int scrollX = getScrollX();
                if (scrollX >= getWidth() || scrollX <= -getWidth()) {
                    if (DEBUG) {
                        Log.d(TAG, "computeScroll ");
                    }
                    setVisibility(INVISIBLE);
                    if (null != mSwipeListener) {
                        mSwipeListener.onSwipe();
                    }
                    setOrintationNONE();
                }
                if(scrollX == 0 ){
                    setOrintationNONE();
                }
            }else if(isVertical()){
                int scrollY = getScrollY();
                if (scrollY >= getHeight() || scrollY <= -getHeight()) {
                    if (DEBUG) {
                        Log.d(TAG, "computeScroll ");
                    }
                    setVisibility(INVISIBLE);
                    if (null != mSwipeListener) {
                        mSwipeListener.onSwipe();
                    }

                    setOrintationNONE();
                }
                if(scrollY == 0){
                    setOrintationNONE();
                }
            }

        }
    }
}
